#####################################################################
# File:         Action.py
# Product:      KnowledgeEngine
#
# Copyright:    Copyright (c) 2003, Faulkner Ltd.
# Author:       Brian Oliver
#
# Description:  This file defines the abstract Action class, the 
#               base class of all Actions.
#
#               Actions are a primitive Objects that perform some type
#               of end-user defined task, typically when some
#               event occurs.
#
# See Also:     GenericObject, ActionContainer, Event
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Common import *
from GenericObject import GenericObject, GenericObjectInfo
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.KERLProcessor import *
from Products.KnowledgeEngine.KERFProcessor import *

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from ImageFile import ImageFile
from Acquisition import *

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## The Standard Action Types 
## (see also: Event types in EventDefinition class)
at_SERVER = 1
at_BROWSER = 2

#####################################################################
## ElementInfo Class Definition
class ActionInfo(GenericObjectInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """
    
    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Returns the name of the class for which 
            we are providing information.
        """
        return 'Action'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "Action"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "action"

    #---------------------------------------------------------------#

    def isInstanceOf(self, className):
        """
            Returns if the class is an instance of the specified
            className, or implements the interface specified 
            by the className
        """

        return className == 'Action' or GenericObjectInfo.isInstanceOf(self, className)
        
    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in 
            the specified container (containerInstance)
            
            NOTE: This is from this class' instance perspective.
        """
        
        #DEFAULT RULE: Actions are only permitted in Events and ActionContainers (that are of compatible types)
        if containerInstance != None:
            return (containerClassInfo.isInstanceOf("ActionContainer") and ((containerInstance.getClassInfo().getType() and self.getType()) <> false)) or (containerClassInfo.isInstanceOf('Event') and ((containerInstance.getDefinition().getType() and self.getType()) <> false))
        else:
            return containerClassInfo.isInstanceOf("ActionContainer") or containerClassInfo.isInstanceOf('Event')       

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a 
            child of the class' instances.
            
            NOTE: This is from this class' instance perspective.
            
            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """
        
        #DEFAULT RULE: Actions can't have Children (only ActionsContainers can have children)
        return false
    
    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific properties using the PropertyReflection interface.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """

        #initialise the super-class properties for reflection
        GenericObjectInfo.onConfigureProperties(self)
        
        #hide the identity property
        self.getPropertyDefinition('identity').setIsForPropertyEditor(false)
        
        #hide the id property
        self.getPropertyDefinition('id').setIsForPropertyEditor(false)

        #hide the title property
        self.getPropertyDefinition('title').setIsForPropertyEditor(false)

        #add the 'order' property        
        self.addPropertyDefinition(PropertyDefinition(identity="order", displayName="Order", description="The relative position of the action with in it's container", defaultValue=1.0, propertyType=pt_FLOAT, propertyFormat=pf_NATIVE, propertyStructure=ps_ATOMIC, isForConstructor=false, isForPropertyEditor=false))        
    
    #---------------------------------------------------------------#

    def getType(self):
        """
            Return the where the Action instances of this class
            may be executed; at_SERVER and at_BROWSER are valid types
            This is directly related to the Event types.  Action
            types may be order together if they support multiple
            locations of execution.
        """
        
        return at_SERVER
        
    #---------------------------------------------------------------#

#####################################################################
## Action Class Definition
class Action(GenericObject):
    """
        Base class for all KnowledgeEngine Actions
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = ActionInfo()

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the Element"        
        
        GenericObject.__init__(self, id, identity)

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object 
            has been loaded into memory.  
            
            This is useful for performing backwards compatibility
        """

        #preform default onAfterInstanciation processing
        GenericObject.onAfterInstanciation(self)
        
        ###print "DEBUG: Element.onAfterInstanciation: Completed"

    #---------------------------------------------------------------#

    def getEnvironment(self):
        "Return the KnowledgeEngine Environment in which this Action is located"
        
        lParent = self.getParent()
        
        while not lParent.isInstanceOf("Environment"):
            lParent = lParent.getParent()
        
        return lParent
        
    #---------------------------------------------------------------#

    def isPreviewPermitted(self):
        """
            Return if the Element is allowed to be previewed.
            
            By default all elements can't be previewed, some however
            should can be previewed. eg: HTMLHeaderFooters
        """
        
        return false
        
    #---------------------------------------------------------------#
    
    def execute(self, assessmentCache, previousActionSuccess=true):
        """
            ABSTRACT: Attempts to execute the defined action 
            (on the SERVER), returning true if the action performed 
            some task or false if no tasks where executed/there was an error
            
            previousActionSuccess: specifies if the immediate action at the same level was successful.
        """            
        
        #assume the action doesn't do anything
        return false
        
    #---------------------------------------------------------------#
    
#####################################################################
## Class Initialisation
# (none)
